#include <Windows.h>
#include "..\GDK\DarkGDK_Classes.h"
#include "TGameObject.h"
#include "GameEngine.h"
#include "IClickable.h"

#include "Psapi.h"
#pragma comment (lib, "psapi.lib")

GameEngine::GameObjectList GameEngine::ObjectsToAdd;

GameEngine::GameObjectList GameEngine::ObjectsToRemove;

GameEngine::GameObjectList GameEngine::Objects;

GameEngine::GameObjectList GameEngine::ObjectsCollidable;

DWORD GameEngine::time = 0;

XSync* GameEngine::gSync = new XSync();

Background* GameEngine::ActiveBackground = NULL;

void GameEngine::MainLoopProcess()
{           
    BOOL bMouseClick = dbMouseClick();
    POINT pt;
    pt.x = dbMouseX();
    pt.y = dbMouseY();
    time = timeGetTime();

    // Draw background
    if (ActiveBackground)
    {
        ActiveBackground->OnDraw();
        ActiveBackground->DoAction();        
    }

    GameObjectList::iterator it = Objects.begin();   
    for (;it != Objects.end();it++)
    {
        TGameObject *obj = *it;
        // IClickable
        IClickable *objClickable = dynamic_cast<IClickable *> (obj);//( dynamic_cast<IBase *>(obj) ) ;
        if (objClickable)
        {
            RECT* rect = objClickable->GetRect();
            if (rect)
            {            
                if (::PtInRect(rect, pt))
                {
                    if (bMouseClick) 
                        objClickable->OnClick(pt.x, pt.y);
                    else
                        objClickable->OnHover(pt.x, pt.y);                    
                }else{
                    objClickable->OnLeave();
                }
            }
        }

        // IInteractive
        IInteractive *objInteractive = dynamic_cast<IInteractive *>( dynamic_cast<IBase *>(obj) ) ;
        if (objInteractive) objInteractive->DoAction();

        obj->OnDraw();            
    }
    
    // Collisions       
    if (!ObjectsCollidable.empty())
    {    

        GameObjectList::iterator itColl1 = ObjectsCollidable.begin();        
        for (; itColl1 != ObjectsCollidable.end(); itColl1++)
        {   

            GameObjectList::iterator itColl2 = itColl1;
            itColl2++;
            for (; itColl2 != ObjectsCollidable.end(); itColl2++)
            {
                RECT r;
                //RECT *rect1 = (*itColl1)->GetRect();
                //RECT *rect2 = (*itColl2)->GetRect();
                TGDKSprite* spr1 = (*itColl1)->GetMainSprite();
                TGDKSprite* spr2 = (*itColl2)->GetMainSprite();
                if (spr1 && spr1)
                if (spr1->Collision(spr2))
                //if (IntersectRect(&r, rect1, rect2))
                {
                    ICollidable * obj1 = dynamic_cast<ICollidable *>(*itColl1);
                    ICollidable * obj2 = dynamic_cast<ICollidable *>(*itColl2);
                    obj1->GetCollision(*itColl2);
                    obj2->GetCollision(*itColl1);                
                }            
            }
        }   
    }

    // GameState    
    GameState* state = GameState::GetActiveState();
    if (state) 
    {
        state->DoAction();
        state->OnDraw();
    }

    // Delete objects
    if (!ObjectsToRemove.empty())
    {    
        GameObjectList::iterator it;
        while ((it = ObjectsToRemove.begin()) != ObjectsToRemove.end())
        {
            ICollidable *objCollidable = dynamic_cast<ICollidable *>(*it);
            if (objCollidable) 
            {
                ObjectsCollidable.remove(*it);
            }
                 
            Objects.remove(*it);
            
            delete (*it); 
            ObjectsToRemove.remove(*it);
        }
        //ObjectsToRemove.clear();
    }
    // Add new objects
    if (!ObjectsToAdd.empty())
    {            
        Objects.insert(Objects.end(), ObjectsToAdd.begin(), ObjectsToAdd.end());

        GameObjectList::iterator it = ObjectsToAdd.begin();
        for(; it != ObjectsToAdd.end();it++)
        {
            ICollidable *objCollidable = dynamic_cast<ICollidable *>(*it);
            if (objCollidable) ObjectsCollidable.push_back(*it);
        }

        ObjectsToAdd.clear();
    }      

    // update GameState (switch)
    GameState::Update();

    // Draw statistical info
    dbInk(RGB(0,0,255), RGB(0,0,255));
    dbText(0,480-40,dbStr((int)Objects.size()));   
    //dbText(0,488-60,dbStr((int)IBase::GetTotalMemory()));
}

void GameEngine::ClearObjects()
{
    ObjectsToRemove.assign(Objects.begin(), Objects.end());
}

void GameEngine::AddObject( TGameObject *obj )
{
    ObjectsToAdd.push_back(obj);
}

void GameEngine::RemoveObject( TGameObject *obj )
{
    ObjectsToRemove.push_back(obj);
}

DWORD GameEngine::GetTime()
{
    return time;
}

void GameEngine::Lock()
{
    gSync->Lock();
}

void GameEngine::Unlock()
{
    gSync->Unlock();
}

void GameEngine::CheckProcessMemLeaks()
{
    PROCESS_MEMORY_COUNTERS pr;
    pr.cb = sizeof(pr);        
    if (GetProcessMemoryInfo(GetCurrentProcess(), &pr, sizeof(pr) ))
    {        
        int metr = pr.WorkingSetSize / 1024 / 1024;
        if (metr>150)
        {
            __asm INT 3;
        }
    }
}

void GameEngine::SetBackground( Background *back )
{
    if (ActiveBackground != NULL) delete ActiveBackground;
    ActiveBackground = back;
}

Background* GameEngine::GetBackground( )
{
    return ActiveBackground;
}




